package com.xframe.xdal.core.domain;

import com.xframe.xdal.core.DataBaseAccess;
import com.xframe.xdal.core.constant.ErrorCode;
import com.xframe.xdal.core.es.ESCilent;
import com.xframe.xdal.core.exception.DalFrameException;
import com.xframe.xdal.core.model.*;
import com.xframe.xdal.core.model.mapping.IColumnMapping;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.mapping.TableInfoBuilder;
import com.xframe.xdal.core.model.page.IPagerModel;
import com.xframe.xdal.core.tran.IDbTransaction;
import com.xframe.xdal.core.util.XReflect;
import lombok.extern.log4j.Log4j2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 领域模型的基础ES Repository接口基础实现
 *
 * @author xufeng
 * @version 1.0
 * @date 2023-03-10
 */
@Log4j2
public class EsBaseRepository implements IRepository{
    @Override
    public void init() {

    }

    @Override
    public DataBaseAccess getDataBaseAccess() {
        return null;
    }

    @Override
    public IDbTransaction beginTransaction() {
        return null;
    }

    @Override
    public IDbTransaction beginTransaction(int level) {
        return null;
    }

    @Override
    public void commitTran() {

    }

    @Override
    public void rollBackTran() {

    }

    @Override
    public <T> T queryModle(Class<?> dataType, FindOptions findOptions) {
        try {
            T collection = ESCilent.getInstance().findAll(TableInfoBuilder.BuildTableInfoByAnnotation(dataType),dataType,findOptions);
            return collection;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer createNew(IModel model) throws DalFrameException {
        return createNew(model,TableInfoBuilder.BuildTableInfoByAnnotation(model.getClass()));
    }

    @Override
    public Integer createNew(IModel model, ITableInfo tableInfo) throws DalFrameException {
        try {
            DataAccessResult<Integer> result = ESCilent.getInstance().addDocument(tableInfo,model,null);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer save(IModel model, ITableInfo tableInfo) throws DalFrameException {
        try {
            DataAccessResult<Integer> result = ESCilent.getInstance().addDocument(tableInfo,model,null);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer createOrUpdate(IModel model, ITableInfo tableInfo) throws DalFrameException {
        try {
            DataAccessResult<Integer> result = ESCilent.getInstance().addDocument(tableInfo,model,null);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer update(IModel model, ITableInfo tableInfo) throws DalFrameException {
        try {
            return  ESCilent.getInstance().updateDocument(tableInfo,model);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer update(IModel model, ITableInfo tableInfo, UpdateAttr updateAttr) throws DalFrameException {
        try {
            return  ESCilent.getInstance().updateDocument(tableInfo,model);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer deleteById(Object id, ITableInfo tableInfo) throws DalFrameException {
        try {
            DataAccessResult<Integer> result = ESCilent.getInstance().deleteDocument(tableInfo,id.toString());
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Integer delete(IModel model, ITableInfo tableInfo) throws DalFrameException {
        try {
            DataAccessResult<Integer> result = ESCilent.getInstance().deleteDocument(tableInfo,model.getEsId());
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public boolean exists(IModel model) throws DalFrameException {
        return exists(model,TableInfoBuilder.BuildTableInfoByAnnotation(model.getClass()));
    }

    @Override
    public boolean exists(IModel model, ITableInfo tableInfo) throws DalFrameException {
        List<IColumnMapping> columnMappingList = tableInfo.findUniqueKeyList();
        List<Object> vals = new ArrayList<>();
        if(columnMappingList != null && columnMappingList.size() > 0){
            for(IColumnMapping columnMapping : columnMappingList){
                vals.add(XReflect.getFieldValue(model,columnMapping.getFieldName()));
            }
        }
        if(vals.size() > 0){
            DataAccessResult result = ESCilent.getInstance().findbyAkOperate(model.getClass(),tableInfo,vals);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult() != null;
        }
        return false;
    }

    @Override
    public <T> IPagerModel<T> queryModleByPage(Class<?> dataType, ITableInfo tableInfo, FindOptions findOptions) {
        try {
            IPagerModel<T> baseModelIPagerModel =  ESCilent.getInstance().findAllByPage(tableInfo,dataType,findOptions);
            return baseModelIPagerModel;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <T> T queryModle(Class<?> dataType, ITableInfo tableInfo, FindOptions findOptions) {
        try {
            T collection = ESCilent.getInstance().findAll(tableInfo,dataType,findOptions);
            return collection;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <T> T findByPK(Class<?> dataType, Object id, ITableInfo tableInfo, String... refNames) {
        try {
            return ESCilent.getInstance().findOne(tableInfo,dataType,id);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <T> T findByPK(Class<?> dataType, Object id, ITableInfo tableInfo) {
        try {
            return ESCilent.getInstance().findOne(tableInfo,dataType,id);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <T> T findbyAk(Class<?> dataType, Object code, ITableInfo tableInfo, String... refNames) {
        try {
            return ESCilent.getInstance().findbyAk(dataType,tableInfo,code);
        } catch (DalFrameException e) {
            throw e;
        }
    }

    @Override
    public <T> T findbyAk(Class<?> dataType, Collection<Object> codes, ITableInfo tableInfo, String... refNames) {
        try {
            DataAccessResult result = ESCilent.getInstance().findbyAkOperate(dataType,tableInfo,codes);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return (T) result.getResult();
        } catch (DalFrameException e) {
            throw e;
        }
    }

    @Override
    public <T> T findbyAk(Class<?> dataType, Object code) {
        try {
            return ESCilent.getInstance().findbyAk(dataType,code);
        } catch (DalFrameException e) {
            throw e;
        }
    }

    @Override
    public Integer deleteMany(ITableInfo tableInfo, ConditionValueCollection whereCollection) {
        return null;
    }

    @Override
    public <E> Integer batchCreate(Class<?> dataType, Collection<E> collection, Integer maxDataLength) {
        try {
            return ESCilent.getInstance().batchAddDocument(dataType,collection);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <E> Integer batchSave(Class<?> dataType, Collection<E> collection, Integer maxDataLength) {
        try {
            return ESCilent.getInstance().batchAddDocument(dataType,collection);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <E> Integer batchSave(Class<?> dataType, Collection<E> collection) {
        try {
            return ESCilent.getInstance().batchAddDocument(dataType,collection);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public <E> DelAndSaveRes deleteAndSave(ITableInfo tableInfo, Class<?> dataType, String keyName, Object keyValue, Collection<E> collection, Integer maxDataLength) throws DalFrameException {
        return null;
    }

    @Override
    public Integer updateMany(ITableInfo tableInfo, SetWrapCollection setWrapCollection, ConditionValueCollection whereCollection) {
        return 0;
//        try {
//            return ESCilent.getInstance().batchUpdateDocument(collection,tableInfo);
//        } catch (DalFrameException e) {
//            e.printStackTrace();
//            throw e;
//        }
    }
}
